package com.quectel.cms.controller.home;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.util.sys.SysCodeUtils;
import com.quectel.business.common.workorder.WorkOrderBusiness;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.cms.vo.home.*;
import com.quectel.cms.vo.propertybill.PropertyBillCountVo;
import com.quectel.constant.core.propertybill.PropertyBillConstants;
import com.quectel.constant.core.workorder.WorkOrderConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.sys.SysCodeKeyConstants;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.household.service.HouseholdService;
import com.quectel.core.module.propertybill.dto.PropertyBillDto;
import com.quectel.core.module.propertybill.dto.PropertyChargeableListDto;
import com.quectel.core.module.propertybill.service.PropertyBillService;
import com.quectel.core.module.propertybill.service.PropertyChargeableListService;
import com.quectel.core.module.propertybill.vo.PropertyBillAmountCountVo;
import com.quectel.core.module.village.service.VillageBuildingService;
import com.quectel.core.module.village.service.VillageRoomService;
import com.quectel.core.module.workorder.dto.WorkOrderDto;
import com.quectel.core.module.workorder.service.WorkOrderService;
import com.quectel.sys.module.sys.dto.SysCodeDto;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/02/17 16:42
 */
@RestController
@RequestMapping("home/property")
@Tag(name = "HomePropertyController", description = "物业管理首页相关api")
@Slf4j
public class HomePropertyController extends BaseController {

    @DubboReference
    private DeptPersonService deptPersonService;
    @DubboReference
    private VillageBuildingService buildingService;
    @DubboReference
    private VillageRoomService roomService;
    @DubboReference
    private HouseholdService householdService;
    @DubboReference
    private WorkOrderService workOrderService;
    @DubboReference
    private PropertyBillService propertyBillService;
    @DubboReference
    private PropertyChargeableListService propertyChargeableListService;

    @Autowired
    private WorkOrderBusiness workOrderBusiness;


    /**
     * 物业费统计
     */
    @GetMapping("propertyBillHouseholdCount")
    @Operation(summary = "物业费户数统计")
    public Response<PropertyBillRoomCountVo> propertyBillHouseholdCount(
            @Parameter(description = "小区id") @RequestParam Long villageId
    ) {
        PropertyBillRoomCountVo propertyBillRoomCountVo = new PropertyBillRoomCountVo();

        Map<String, Object> params = new HashMap<>();
        //查询缴费户数
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        //未缴费
        params.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        propertyBillRoomCountVo.setNotPayCount(propertyBillService.countRoom(params));
        //已缴费
        params.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.PAID_STATUS_LIST);
        propertyBillRoomCountVo.setPaidCount(propertyBillService.countRoom(params));
        //逾期
        params.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getOverdueStatus), SystemConstants.NORMAL);
        propertyBillRoomCountVo.setOverdueCount(propertyBillService.countRoom(params));

        return Response.<PropertyBillRoomCountVo>ok().wrap(propertyBillRoomCountVo);
    }


    /**
     * 物业费统计
     */
    @GetMapping("propertyBillCount")
    @Operation(summary = "物业费账单统计")
    public Response<PropertyBillCountVo> propertyBill(
            @Parameter(description = "小区id") @RequestParam Long villageId
    ) {
        PropertyBillCountVo propertyBillCountVo = new PropertyBillCountVo();

        Map<String, Object> accountsReceivableParams = new HashMap<>();
        accountsReceivableParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        accountsReceivableParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        PropertyBillAmountCountVo propertyBillAmountCountVo = propertyBillService.countAmount(accountsReceivableParams);
        //应收
        propertyBillCountVo.setTotalAmount(propertyBillAmountCountVo.getTotalAmount());

        Map<String, Object> accountsReceivedParams = new HashMap<>();
        accountsReceivedParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        accountsReceivedParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);

        //支付成功
        accountsReceivedParams.put(LambdaUtil.getFieldName(PropertyBillDto::getPayStatus), PropertyBillConstants.PayStatus.PAY_SUCCESS.getStatusValue());
        PropertyBillAmountCountVo accountsReceivedAmount = propertyBillService.countAmount(accountsReceivedParams);
        //实收
        propertyBillCountVo.setPaidAmount(accountsReceivedAmount.getTotalAmount());
        //查询所有的
        return Response.<PropertyBillCountVo>ok().wrap(propertyBillCountVo);
    }


    /**
     * 物业费统计
     */
    @GetMapping("propertyBillTypeCount")
    @Operation(summary = "物业费种类统计")
    public Response<CommonPieResp> propertyBillTypeCount(
            @Parameter(description = "小区id") @RequestParam Long villageId
    ) {
        CommonPieResp commonPieResp = new CommonPieResp();
        //查看所有的收费标准
        Map<String, Object> chargeableListParams = new HashMap<>();
        chargeableListParams.put(LambdaUtil.getFieldName(PropertyChargeableListDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        chargeableListParams.put(LambdaUtil.getFieldName(PropertyChargeableListDto::getVillageId), villageId);
        List<PropertyChargeableListDto> propertyChargeableListDtos = propertyChargeableListService.queryList(chargeableListParams);

        //如果没有则标记为0
        if (CollectionUtils.isEmpty(propertyChargeableListDtos)) {
            commonPieResp.setTotal(0d);
            CommonPieResp.PieInfo pieInfo = new CommonPieResp.PieInfo("收费项目", 0d);
            commonPieResp.setPieData(new CommonPieResp.PieInfo[]{pieInfo});
            return Response.<CommonPieResp>ok().wrap(commonPieResp);
        }

        Map<String, Object> accountsReceivableParams = new HashMap<>();
        accountsReceivableParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        accountsReceivableParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        PropertyBillAmountCountVo propertyBillAmountCountVo = propertyBillService.countAmount(accountsReceivableParams);
        //应收
        commonPieResp.setTotal(propertyBillAmountCountVo.getTotalAmount().doubleValue());

        List<CommonPieResp.PieInfo> pieInfos = new ArrayList<>();
        for (PropertyChargeableListDto propertyChargeableListDto : propertyChargeableListDtos) {
            //根据不同的收费标准查询
            accountsReceivableParams.put(LambdaUtil.getFieldName(PropertyBillDto::getChargeableListId), propertyChargeableListDto.getId());
            PropertyBillAmountCountVo countAmount = propertyBillService.countAmount(accountsReceivableParams);
            CommonPieResp.PieInfo pieInfo = new CommonPieResp.PieInfo(propertyChargeableListDto.getName(), countAmount.getTotalAmount().doubleValue());
            pieInfos.add(pieInfo);
        }

        commonPieResp.setPieData(pieInfos.toArray(new CommonPieResp.PieInfo[0]));

        //查询所有的
        return Response.<CommonPieResp>ok().wrap(commonPieResp);
    }

    /**
     * 投诉建议
     */
    @GetMapping("complaintList")
    @Operation(summary = "工单列表-返回投诉举报大类的数据")
    public Response<Page<ComplaintResp>> complaintList(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "小区id") @RequestParam Long villageId
    ) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        request.put(LambdaUtil.getFieldName(WorkOrderDto::getCategory), WorkOrderConstants.WorkOrderCategory.WORK_ORDER_COMPLAINT.getCategory());

        super.fillAuthorityData(request.getParams());
        int total = workOrderService.queryTotal(request.getParams());

        List<WorkOrderDto> list = null;

        List<ComplaintResp> respList = new ArrayList<>();
        if (total > 0) {
            list = workOrderService.queryList(request.getParams());
            for (WorkOrderDto workOrderDto : list) {
                WorkOrderDto workOrderResp = workOrderBusiness.selectById(workOrderDto.getId());
                ComplaintResp resp = new ComplaintResp();
                resp.setComplainant(workOrderResp.getOrderSourceUsername());
                resp.setCreateTime(workOrderResp.getCreateTime());
                resp.setTypeName(SysCodeUtils.easyToGetName(WorkOrderConstants.WorkOrderCategory.WORK_ORDER_COMPLAINT.getMark(), workOrderResp.getType() + ""));
                resp.setDetail(workOrderResp.getDetail());
                resp.setStatusName(workOrderResp.getStatusName());
                respList.add(resp);
            }
        } else {
            list = new ArrayList<>();
        }

        Page<ComplaintResp> page = new Page<>(request.getPageNo(), request.getPageSize(), total, respList);
        return Response.<Page<ComplaintResp>>ok().wrap(page);
    }


    /**
     * 工单统计（状态分类）
     * 根据工单状态 进行统计
     */
    @GetMapping("workOrderStatusStatistics")
    @Operation(summary = "工单统计-按状态分组")
    public Response<List<WorkOrderCountVo>> workOrderStatusStatistics(
            @Parameter(description = "小区id") @RequestParam Long villageId) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));
        super.fillAuthorityData(request.getParams());

        List<SysCodeDto> categoryCodeList = SysCodeUtils.easyToGetByMark(SysCodeKeyConstants.WORK_ORDER_STATUS);
        List<WorkOrderCountVo> eventList = new ArrayList<>();
        for (SysCodeDto sysCodeDto : categoryCodeList) {
            WorkOrderCountVo pieInfo = new WorkOrderCountVo();
            pieInfo.setName(sysCodeDto.getName());
            request.put(LambdaUtil.getFieldName(WorkOrderDto::getStatus), sysCodeDto.getValue());
            int count = workOrderService.queryTotal(request.getParams());
            pieInfo.setCount(count);
            eventList.add(pieInfo);
        }
        return Response.<List<WorkOrderCountVo>>ok().wrap(eventList);
    }


    /**
     * 物业首页-多维度数量统计
     *
     * @param villageId
     * @return
     */
    @GetMapping("propertyStatisticsInfo")
    @Operation(summary = "物业首页-多维度数量统计")
    public Response<PropertyStatisticsInfoVo> propertyStatisticsInfo(
            @Parameter(description = "小区id") @RequestParam Long villageId) {

        Request request = Request.configParams(Request.parseParams(httpServletRequest));
        super.fillAuthorityData(request.getParams());

        // 物业员工
        int propertyPersonnelCount = deptPersonService.queryTotal(request.getParams());

        // 楼栋
        int buildingCount = buildingService.queryTotal(request.getParams());

        // 房间
        int roomCount = roomService.queryTotal(request.getParams());

        // 业主
        int ownerCount = householdService.queryTotal(request.getParams());


        // 重点人员
        int keyPersonnelCount = 0;
        List<SysCodeDto> sysCodeDtos = SysCodeUtils.easyToGetByMark(SysCodeKeyConstants.HOUSEHOLD_TAG);
        //sysCodeDto在core-service不存在所以转为map(这里不转map dubbo也会自动转)
        request.put("tags", sysCodeDtos.stream().map(v -> BeanUtil.beanToMap(v)).collect(Collectors.toList()));
        Map<String, Double> result = householdService.focusGroupsCount(request.getParams());
        for (Map.Entry<String, Double> entry : result.entrySet()) {
            keyPersonnelCount = keyPersonnelCount + entry.getValue().intValue();
        }

        PropertyStatisticsInfoVo vo = new PropertyStatisticsInfoVo();
        vo.setPropertyPersonnelCount(propertyPersonnelCount);
        vo.setBuildingCount(buildingCount);
        vo.setRoomCount(roomCount);
        vo.setOwnerCount(ownerCount);
        vo.setKeyPersonnelCount(keyPersonnelCount);

        return Response.<PropertyStatisticsInfoVo>ok().wrap(vo);
    }

    /**
     * 工单统计-环形统计
     */
    @GetMapping("workOrderCircularStatistics")
    @Operation(summary = "工单统计-环形统计")
    public Response<CommonPieResp> workOrderCircularStatistics(@Parameter(description = "小区id") Long villageId) {
        Request request = Request.configParams(Request.parseParams(httpServletRequest));
        super.fillAuthorityData(request.getParams());


        int queryTotal = workOrderService.queryTotal(request.getParams());
        List<SysCodeDto> categoryCodeList = SysCodeUtils.easyToGetByMark(SysCodeKeyConstants.WORK_ORDER_CATEGORY);

        List<CommonPieResp.PieInfo> eventList = new ArrayList<>();
        for (SysCodeDto sysCodeDto : categoryCodeList) {
            CommonPieResp.PieInfo pieInfo = new CommonPieResp.PieInfo();
            pieInfo.setName(sysCodeDto.getName());
            request.put(LambdaUtil.getFieldName(WorkOrderDto::getCategory), sysCodeDto.getValue());
            int count = workOrderService.queryTotal(request.getParams());
            pieInfo.setValue(Double.valueOf(count));
            eventList.add(pieInfo);
        }

        CommonPieResp commonCountResp = new CommonPieResp();
        commonCountResp.setTotal(Double.valueOf(queryTotal));
        commonCountResp.setPieData(eventList.toArray(new CommonPieResp.PieInfo[0]));
        return Response.<CommonPieResp>ok().wrap(commonCountResp);
    }

}
